define(function (require, exports, module) {

    var RectUtils = WebPDF.RectUtils;
    var PDFRect = WebPDF.PDFRect;
    /**
     * Name of find tool plugin.
     * @type {string} Name of find tool plugin.
     */
    WebPDF.FindToolPluginName = "Find Tool Plugin";

    /**
     * Enum for search direction
     * @enum
     */
    WebPDF.SearchDirection = {
        Up: 0,
        Down: 1
    };
    /**
     * @constructor
     * @private
     */
    var SearchResult = function () {
        this.startCharIndex = -1;
        this.relateText = "";
        this.rects = [];        //存储搜索结构的矩形区域;
    };


    /**
     * Context for continuous searching
     * @param {String} contentToSearch content to search
     * @param {WebPDF.SearchDirection} searchDirection direction for search
     * @param {Number} curPageIndex current page index
     * @param {Number} startCharIndex current char index
     * @constructor
     * @private
     */
    var ContinuousSearchContext = function (contentToSearch, searchDirection, curPageIndex, startCharIndex) {
        this.content = contentToSearch;
        this.direction = searchDirection;
        this.startPageIndex = curPageIndex;
        this.startCharIndex = startCharIndex;
        this.curPageIndex = curPageIndex;
        this.curCharIndex = startCharIndex;
    };

    /**
     * Searched result of a page.
     * @constructor
     * @private
     */
    var PageSearchResult = function () {
        this.pageIndex = -1;
        this.totalCharCnt = -1;
        this.curResultIndex = -1;
        /**
         * 搜索结果列表
         * @type {Array.<SearchResult>}
         */
        this.resultList = [];
        this.isSearched = false;
        this.isHasResult = false;
        this.clearResult = function () {
            this.pageIndex = -1;
            this.totalCharCnt = -1;
            this.curResultIndex = -1;
            this.resultList = [];
            this.isSearched = false;
            this.isHasResult = false;
        };
        this.isLastResult = function (curSelIndex) {
            return curSelIndex === (this.resultList.length - 1);
        };
        this.isFirstResult = function (curSelIndex) {
            return curSelIndex === 0;
        };
        this.getNextCharIndex = function (curSelIndex) {
            return this.resultList[curSelIndex + 1].startCharIndex;
        };
        this.getPrevCharIndex = function (curSelIndex) {
            return this.resultList[curSelIndex - 1].startCharIndex;
        };
        this.getLastCharIndex = function () {
            var lastResultIndex = this.resultList.length - 1;
            if (lastResultIndex < 0) {
                lastResultIndex = 0;
            }
            var lastResult = this.resultList[lastResultIndex];
            return lastResult ? lastResult.startCharIndex : 0;
        };
    };

    /**
     * Context for searching
     * @constructor
     * @private
     */
    var SearchContext = function () {
        /**
         * Text to find
         * @type {string}
         */
        this.findWhat = "";
        /**
         * Results of rect
         * @type {Array.<WebPDF.PDFRect>}
         */
        this.resultRectArray = [];
        /**
         * The starting position to search(in text objects)
         * @type {number}
         */
        this.searchPos = -1;
        /**
         * The starting position of the result in chars
         * @type {number}
         */
        this.resultCharStartPos = -1;
        /**
         * The starting position of the result in items
         * @type {number}
         */
        this.resultItemStartPos = -1;
        /**
         * The ending position of the result in items
         * @type {number}
         */
        this.resultItemEndPos = -1;
        /**
         * Whether to match case
         * @type {boolean}
         */
        this.isMatchCase = false;
        /**
         * Whether to match whole word
         * @type {boolean}
         */
        this.isMatchWholeWord = false;
        /**
         * Whether there is any result.
         * @type {boolean}
         */
        this.isFound = false;
    };

    var FindResult = function () {
        this.startIndex = -1;
        this.endIndex = -1;
        this.resultCharStartPos = -1;
    };
    /**
     * Parameters for searching
     * @constructor
     * @private
     */
    var SearchParams = function () {
        this.startCharIndex = -1;
        this.endCharIndex = -1;
    };

    /**
     * 进行下一次搜索的参数;
     * @param {Number} pageIndex 页面索引;
     * @param {Number} charIndex 相对于页面的字符索引;
     * @private
     */
    var NextSearchParam = function (pageIndex, charIndex) {
        this.pageIndex = pageIndex;
        this.charIndex = charIndex;
    };

    /**
     * Plugin of find tool
     * @param {WebPDF.ReaderApp} readerApp app instance
     * @extends {WebPDF.IReaderPlugin}
     * @constructor
     */
    WebPDF.FindToolPlugin = function (readerApp) {
        var _readerApp = readerApp,
            _isSearching = false,
            _isCaseSensitive = false,
            _isMatchWholeWord = false,
            _contentToSearch = "",
            _tempContentToSearch = "",
            _curSearchedPageIndex = -1,					 //上一次搜索结果所处页面;
            _curSearchedCharIndex = -1,                  //上一次搜索结果的字符索引;
            _curSelectedResultIndex = -1,                     //上一次搜索结果相对于页面搜索结果的索引（一个页面包含多个搜索结果 SearchResult）;
            /**
             * Cache for page results.
             * @type {Array.<PageSearchResult>}
             * @private
             */
            _pageFindCacheResults = [],
            _textManager = _readerApp.getTextManager(),
            _searchDivId = null,
            _searchLoadingTextId = _readerApp.getAppId() +"_searchLoadingText",  //搜索层文本ID
            //_searchTextInputId = _readerApp.getAppId() + "_searchTextInput",
            _highlightRects = null,				//当前需要高亮的矩形区域;
            _highlightDivCreatedPageList = {},		// 存储已经创建highlight div的页面索引,格式为 :   页面索引：true/fase;
            _isSearchingBlocked = false,		//当前搜索是否block住（正在从服务端获取文本)
            /**
             * 上一次搜索的上下文
             * @type {ContinuousSearchContext}
             * @private
             */
            _continuousSearchContext = null,
            _isCancelSearch = false,
            /**
             * 搜索loading的回调，用于处理loading显示的定制化
             * @private
             */
            _searchLoadingCallback = null;
            //_self = this;

        /**
         * Check whether current search an new search.
         * @param contentToSearch content to search
         * @returns {boolean} return true if current search is an new search.
         * @private
         */
        function _isNewSearch(contentToSearch) {
            return !(_contentToSearch === contentToSearch);
        }

        /**
         * Clear all searched results.
         * @private
         */
        function _clearSearchedResults() {
            _contentToSearch = '';
            _resetHighLightText(true);
            _curSearchedCharIndex = -1;
            _curSearchedPageIndex = -1;
            _curSelectedResultIndex = -1;
            var pageCount = _readerApp.getMainView().getDocView().getPageCount();
            for (var i = 0; i < pageCount; i++) {
                _pageFindCacheResults[i].clearResult();
            }
        }

        /**
         * Get id of highlight div for a page view.
         * @param pageView page view.
         * @returns {string} id of highlight div for a page view.
         * @private
         */
        function _getTextHighlightDivId(pageView) {
            return pageView.getPageViewContainerID() + "_HighLights";
        }

        /**
         * Set parameters for search
         * @param isCaseSensitive Whether to match case
         * @param isMarchWholeWord Whether to match whole world
         */
        this.setSearchParam = function (isCaseSensitive, isMarchWholeWord) {
            if (_isSearching) {
                console.warn("Searching parameters can not be changed during searching.");
                return;
            }
            //如果搜索选项发生改变，意味着已经搜索到的结果都要清除
            if (_isCaseSensitive != isCaseSensitive || _isMatchWholeWord != isMarchWholeWord) {
                _clearSearchedResults();
            }
            _isCaseSensitive = isCaseSensitive;
            _isMatchWholeWord = isMarchWholeWord;
        };

        /**
         * 修改搜索层的显示状态
         * @param isShow 设置为true，则显示搜索层，否则隐藏
         * @private
         */
        function _changedSearchingDivState(isShow) {
            if(_searchLoadingCallback){
               if (_searchLoadingCallback(isShow)) return;
            } 
            var jqSearchDiv = $("#" + _searchDivId);           
            isShow ? jqSearchDiv.show() : jqSearchDiv.hide();                    
        }

        /**
         * Set highlight rects
         * @param {Array.<WebPDF.PDFRect>} rects
         * @private
         */
        function _setHighlightRects(rects) {
            _highlightRects = [];
            _highlightRects = rects.concat();
        }

        /**
         * Reset all highlight text
         * @param {Boolean} isClearHighlightRects if this parameter set to true, the highlight rects will also be clear.
         * @private
         */
        function _resetHighLightText(isClearHighlightRects) {
            if (isClearHighlightRects) {
                _highlightRects = [];
            }
            var pageView = _readerApp.getMainView().getDocView().getPageView(_curSearchedPageIndex);
            if (pageView) {
                var highLightDivID = _getTextHighlightDivId(pageView);
                var jqHighlightDiv = $("#" + highLightDivID);
                if (jqHighlightDiv.length > 0) {
                    jqHighlightDiv.empty();
                }
            }
        }

        function _highlightSearchedText(pageIndex, highlightRects) {
            var docView = _readerApp.getMainView().getDocView();
            var pageCount = docView.getPageCount();
            if (pageIndex < 0 || pageIndex >= pageCount) {
                return false;
            }
            var pageView = docView.getPageView(pageIndex);
            if (!pageView.isContentCreated()) {
                docView.goToPage(pageIndex, 0, 0);
            }
            var offset = _getHighlightOffset2Scroll(pageView, highlightRects);
            if (offset) {
                docView.goToPage(pageIndex, offset.x, offset.y);
            }
            _highLightTextRects(pageView, highlightRects);
        }

        function _highLightTextRects(pageView, highlightRects) {
            if (!pageView || !pageView.isContentCreated() || !highlightRects) {
                return;
            }
            var highLightDivID = _getTextHighlightDivId(pageView);
            var pageIndex = pageView.getPageIndex();
            if (_highlightDivCreatedPageList[pageIndex] == null) {
                var highLightDivHtml = "<div id='" + highLightDivID + "' style='z-index:7;'></div>";
                var jqPageView = $("#" + pageView.getPageViewContainerID());
                jqPageView.append(highLightDivHtml);
                _highlightDivCreatedPageList[pageIndex] = true;
            }
            var jqHighlightDiv = $("#" + highLightDivID);
            jqHighlightDiv.empty(); //清空原有的div内容;

            var highLightDivContent = "";
            for (var i = 0; i < highlightRects.length; i++) {
                var rect = highlightRects[i];
                RectUtils.normalize(rect);
                rect = pageView.pdfToDoc(rect, true);
                highLightDivContent += "<div id='" + "highlight_" + pageIndex + "_" + i + "'class='fwr-search-text-highlight' style='left:" +
                    rect.left + "px;top:" + rect.top + "px;width:" + RectUtils.width(rect) + "px;height:" + RectUtils.height(rect) + "px' ></div>";
            }
            jqHighlightDiv.append(highLightDivContent);
        }

        /**
         * 根据页面和需要高亮的区域，获取滚动条需要移动的位置; 返回null代表可见或获取失败
         * @param pageView page view
         * @param highlightRects rects to highlight
         * @returns { {x: {Number}, y: {Number}} | null }
         * @private
         */
        function _getHighlightOffset2Scroll(pageView, highlightRects) {
            if (highlightRects.length <= 0) {
                return null;
            }
            var firstRect = highlightRects[0];
            RectUtils.normalize(firstRect);
            var unionRect = new PDFRect(firstRect.left, firstRect.top, firstRect.right, firstRect.bottom);
            for (var i = 1; i < highlightRects.length; i++) {
                var tmpRect = highlightRects[i];
                RectUtils.normalize(tmpRect);
                RectUtils.union(unionRect, tmpRect);
            }
            var docView = _readerApp.getMainView().getDocView();
            var jqDocView = $("#" + docView.getDocViewContainerID());
            var pagesContainerHeight = jqDocView.height(), pagesContainerWidth = jqDocView.width(),
                pagesContainerOffset = jqDocView.offset();
            var jqPageView = $("#" + pageView.getPageViewContainerID());
            var viewMode = pageView.getDocView().getViewMode();
            switch (viewMode) {
                case WebPDF.PDFView.RD_BRMODE_CONTINUOUS_FACING:
                {
                    //双页模式，暂时不处理
                }
                    break;
                case WebPDF.PDFView.RD_BRMODE_CONTINUOUS:
                {
                    var pageOffset = jqPageView.offset();
                    var docRect = pageView.pdfToDoc(unionRect, true);
                    var docHeight = RectUtils.height(docRect);
                    var docWidth = RectUtils.width(docRect);
                    var centerY = pagesContainerHeight / 2;
                    var centerX = pagesContainerWidth / 2;
                    var isVisible = ( (pageOffset.top + docRect.top >= pagesContainerOffset.top) &&
                        (pageOffset.top + docRect.top <= pagesContainerOffset.top + pagesContainerHeight) )
                        || ( (pageOffset.top + docRect.top <= pagesContainerOffset.top) &&
                            (pageOffset.top + docRect.top + docHeight >= pagesContainerOffset.top) );
                    isVisible &= ( (pageOffset.left + docRect.left >= pagesContainerOffset.left) &&
                        (pageOffset.left + docRect.left <= pagesContainerOffset.left + pagesContainerWidth) )
                        || ( (pageOffset.left + docRect.left <= pagesContainerOffset.left) &&
                            (pageOffset.left + docRect.left + docWidth >= pagesContainerOffset.left));

                    if (isVisible) {
                        return null;
                    }
                    var pageTopPosY = docHeight / 2 + docRect.top;
                    pageTopPosY = centerY - pageTopPosY;
                    pageTopPosY = -pageTopPosY;
                    var pageLeftPosX = docWidth / 2 + docRect.left;
                    pageLeftPosX = centerX - pageLeftPosX;
                    pageLeftPosX = -pageLeftPosX;
                    return { x: pageLeftPosX, y: pageTopPosY };
                }
                    break;
                default:
                    break;
            }
            return null;
        }

        /**
         * Cancel searching
         */
        this.cancelSearching = function () {
            if (!_isSearching) {
                return;
            }
            _continuousSearchContext = null;
            _isSearchingBlocked = false;
            _isCancelSearch = true;
        };


        this.setSearchLoadingCallback = function(searchLoadingCallback){
            _searchLoadingCallback = searchLoadingCallback;
        };

        /**
         * Continue to search
         * @returns {boolean}  return true if the text can be found.
         * @private
         */
        function _continueToSearch() {
            if (_continuousSearchContext) {
                _isSearchingBlocked = false;
                var bFound = false;
                var totalPageCount = _readerApp.getMainView().getDocView().getPageCount();
                _tempContentToSearch = _continuousSearchContext.content;
                if (_continuousSearchContext.direction == WebPDF.SearchDirection.Down) {
                    if (_continuousSearchContext.curPageIndex >= _continuousSearchContext.startPageIndex) {
                        bFound = _searchInRange(_continuousSearchContext.curPageIndex, totalPageCount - 1, _continuousSearchContext.startCharIndex, _continuousSearchContext.direction);
                        if (!bFound)
                            bFound = _searchInRange(0, _continuousSearchContext.startPageIndex, _continuousSearchContext.startCharIndex, _continuousSearchContext.direction); //返回文档头部开始搜
                    }
                    else {
                        bFound = _searchInRange(_continuousSearchContext.curPageIndex, _continuousSearchContext.startPageIndex, _continuousSearchContext.startCharIndex, _continuousSearchContext.direction); //返回文档头部开始搜
                    }
                }
                else {
                    if (_continuousSearchContext.curPageIndex <= _continuousSearchContext.startPageIndex) {
                        bFound = _searchInRange(0, _continuousSearchContext.curPageIndex, _continuousSearchContext.startCharIndex, _continuousSearchContext.direction);
                        if (!bFound)
                            bFound = _searchInRange(_continuousSearchContext.startPageIndex + 1, totalPageCount - 1, _continuousSearchContext.startCharIndex, _continuousSearchContext.direction);
                    }
                    else {
                        bFound = _searchInRange(_continuousSearchContext.startPageIndex + 1, _continuousSearchContext.curPageIndex, _continuousSearchContext.startCharIndex, _continuousSearchContext.direction);
                    }
                }
                if (_isCancelSearch) {
                    _isCancelSearch = false;
                    _changedSearchingDivState(false);
                    return false;
                }
                if (!_isSearchingBlocked) {
                    _continuousSearchContext = null;
                    _changedSearchingDivState(false);
                    if (!bFound) {
                        WebPDF.alert(_readerApp,"", i18n.t("Search.NoFound"), null, null, null, true);
                        $(_readerApp).trigger("NotFound");   
                    }
                    return bFound;
                }
            }
        }

        /**
         * 搜索文本
         * @param {String} contentToSearch 要搜索的文本
         * @param {WebPDF.SearchDirection} searchDirection 搜索的方向
         * @param {Number} curPageIndex 当前页面索引
         * @param {Number} startCharIndex 当前起始字符位置
         * @returns {boolean} 搜索成功返回true，返回返回false
         * @private
         */
        function _searchText(contentToSearch, searchDirection, curPageIndex, startCharIndex) {
            if (_isSearching) {
                return false;
            }
            _continuousSearchContext = new ContinuousSearchContext(contentToSearch, searchDirection, curPageIndex, startCharIndex);
            _isCancelSearch = false;
            var totalPageCount = _readerApp.getMainView().getDocView().getPageCount();
            if (!contentToSearch || curPageIndex < 0) {
                return false;
            }
            _tempContentToSearch = contentToSearch;
            _changedSearchingDivState(true);  //显示搜索层
            _isSearchingBlocked = false;
            var bFound = false;
            var isNewSearch = _isNewSearch(contentToSearch);
            if (isNewSearch) {
                _clearSearchedResults();
            }
            if (searchDirection == WebPDF.SearchDirection.Down) {
                bFound = _searchInRange(curPageIndex, totalPageCount - 1, startCharIndex, searchDirection);
                if (!bFound) {
                    //返回文档头部开始搜
                    bFound = _searchInRange(0, curPageIndex, startCharIndex, searchDirection);
                }
            }
            else {
                bFound = _searchInRange(0, curPageIndex, startCharIndex, searchDirection);
                if (!bFound) {
                    bFound = _searchInRange(curPageIndex + 1, totalPageCount - 1, startCharIndex, searchDirection);
                }
            }
            if (_isCancelSearch) {
                _isCancelSearch = false;
                _changedSearchingDivState(false);
                return false;
            }
            if (!_isSearchingBlocked) {
                _continuousSearchContext = null;
                _changedSearchingDivState(false);
                if (!bFound) {
                    WebPDF.alert(_readerApp,"", i18n.t("Search.NoFound"), null, null, null, true);
                     $(_readerApp).trigger("NotFound");   
                }
                return bFound;
            }
            return bFound;
        }

        /**
         * 根据搜索上下文搜索指定页面范围内的文本
         * @param {Number} startPageIndex 起始页面
         * @param {Number} endPageIndex  结束页面
         * @param {Number} startCharIndex 字符起始索引
         * @param {WebPDF.SearchDirection} searchDirection 搜索方向
         * @returns {boolean} 搜索成功返回true，否则返回false
         * @private
         */
        function _searchInRange(startPageIndex, endPageIndex, startCharIndex, searchDirection) {
            var bFound = false;
            var i;
            if (searchDirection == WebPDF.SearchDirection.Down) {
                for (i = startPageIndex; i <= endPageIndex; i++) {
                    if (!_isCancelSearch) {
                        bFound = _searchInPage(i, startCharIndex, searchDirection);
                        if (bFound) {
                            return true;
                        }
                    }
                    else {
                        return false;
                    }
                }
            }
            else {
                for (i = endPageIndex; i >= startPageIndex; i--) {
                    if (!_isCancelSearch) {
                        bFound = _searchInPage(i, startCharIndex, searchDirection);
                        if (bFound) {
                            return true;
                        }
                    }
                    else {
                        return false;
                    }
                }
            }
            return false;
        }

        /**
         * 在某个页面内搜索文本
         * @param {Number} pageIndex 页面索引
         * @param {Number} startCharIndex 起始字符索引
         * @param {WebPDF.SearchDirection} searchDirection 搜索方向
         * @returns {boolean} 搜索成功返回true，否则返回false
         * @private
         */
        function _searchInPage(pageIndex, startCharIndex, searchDirection) {
            var pageResult = _pageFindCacheResults[pageIndex];
            if (!pageResult || !pageResult.isSearched) {
                var textPage = _createATextPage(pageIndex);
                if (!textPage) {
                    //还未获取到页面文本，等待一段时间后重试
                    if (_isSearchingBlocked) {
                        _continuousSearchContext.curPageIndex = pageIndex;
                        _continuousSearchContext.curCharIndex = startCharIndex;
                        setTimeout(function () {
                            _continueToSearch();
                        }, 100);
                    }
                    //这里需要返回true以暂停搜索
                    return true;
                }

                pageResult = new PageSearchResult();
                pageResult.pageIndex = pageIndex;
                pageResult.totalCharCnt = textPage.getStrSize();
                var searchContext = _createSearchContext();
                var isResultFound = false;
                var result;
                do
                {
                    result = new FindResult();
                    var bFound = _findNext(searchContext, result, textPage);
                    if (bFound) {
                        var bInPage = result.startIndex >= 0;
                        if (bInPage) {
                            isResultFound = true;
                            var findResult = new SearchResult();
                            findResult.startCharIndex = result.resultCharStartPos;
                            findResult.rects = searchContext.resultRectArray;
                            pageResult.resultList.push(findResult);
                        }
                    }
                    else {
                        break;
                    }
                } while (true);

                if (!isResultFound) {
                    return false;
                }
                pageResult.isSearched = true;
                pageResult.isHasResult = true;
                _pageFindCacheResults[pageIndex] = pageResult;
            }

            var findResult = _searchInPageCache(pageResult, startCharIndex, searchDirection);
            if (findResult) {
                _resetHighLightText(true);
                result = findResult.ret;
                var bSameResult = (_curSearchedCharIndex === result.startCharIndex &&
                    _curSelectedResultIndex == findResult.index && _curSearchedPageIndex === pageIndex);
                _curSearchedPageIndex = pageIndex;
                _setHighlightRects(result.rects);
                if (!bSameResult)
                    _highlightSearchedText(_curSearchedPageIndex, _highlightRects);
                else
                    setTimeout(function () {
                        _highlightSearchedText(_curSearchedPageIndex, _highlightRects);
                    }, 50);
                _curSearchedCharIndex = result.startCharIndex;
                _contentToSearch = _tempContentToSearch;
                _tempContentToSearch = "";
                _curSelectedResultIndex = findResult.index;
            }
            return findResult != null;
        }

        /**
         * 在已有的缓存中搜索文本
         * @param {PageSearchResult} pageResult 整个页面的搜索结果
         * @param {Number} startCharIndex 起始字符索引
         * @param {WebPDF.SearchDirection} searchDirection 搜索方向
         * @returns { {ret: {SearchResult}, index: {Number}} | null}  搜索失败返回null，否则返回对应的object
         * @private
         */
        function _searchInPageCache(pageResult, startCharIndex, searchDirection) {
            if (!pageResult || !pageResult.isSearched) {
                return null;
            }
            if (searchDirection == WebPDF.SearchDirection.Down) {
                for (var j = 0; j < pageResult.resultList.length; j++) {
                    var result = pageResult.resultList[j];
                    if (startCharIndex === -1 || result.startCharIndex >= startCharIndex) {
                        return {ret: result, index: j};
                    }
                }
            }
            else {
                for (var j = pageResult.resultList.length - 1; j >= 0; j--) {
                    var result = pageResult.resultList[j];
                    if (startCharIndex === -1 || result.startCharIndex <= startCharIndex) {
                        return {ret: result, index: j};
                    }
                }
            }

            return null;
        }

        /**
         * 创建一个页面文本类对象
         * @param pageIndex 页面索引
         * @returns {*}
         * @private
         */
        function _createATextPage(pageIndex) {
            var textPage = _textManager.getTextPage(pageIndex);
            if (textPage.blocking) {
                _isSearchingBlocked = true;
                return null;
            }
            return textPage;
        }

        /**
         * 根据当前搜索参数构建一个搜索上下文
         * @returns {SearchContext} 搜索上下文
         * @private
         */
        function _createSearchContext() {
            var searchContext = new SearchContext();
            searchContext.isMatchCase = _isCaseSensitive;
            searchContext.isMatchWholeWord = _isMatchWholeWord;
            searchContext.resultRectArray = [];
            searchContext.findWhat = _tempContentToSearch;
            searchContext.searchPos = 0;
            searchContext.resultCharStartPos = -1;
            searchContext.resultItemStartPos = -1;
            searchContext.resultItemEndPos = -1;
            searchContext.searchPos = 0;
            searchContext.isFound = false;
            searchContext.searchPos = 0;
            return searchContext;
        }

        /**
         * 根据当前的搜索上下文，继续向下搜索文本
         * @param {SearchContext} searchContext 搜索上下文
         * @param {FindResult} result 用于返回搜索结果
         * @param textPage 文本页面对象
         * @returns {boolean} 搜索成功返回true，否则返回false
         * @private
         */
        function _findNext(searchContext, result, textPage) {
            //Clear data
            searchContext.resultRectArray = [];
            searchContext.resultItemEndPos = -1;
            searchContext.resultItemStartPos = -1;

            //get next search pos
            if (searchContext.resultCharStartPos != -1) {
                searchContext.searchPos = searchContext.resultCharStartPos + 1;
            }
            if (!_findInPDFPage(searchContext, textPage)) {
                searchContext.isFound = false;
                return false;
            }
            result.startIndex = searchContext.resultItemStartPos;
            result.endIndex = searchContext.resultItemEndPos;
            result.resultCharStartPos = searchContext.resultCharStartPos;
            searchContext.isFound = true;
            return true;
        }

        function _findInPDFPage(searchContext, textPage) {
            searchContext.resultCharStartPos = -1;
            searchContext.resultItemStartPos = -1;
            searchContext.resultItemEndPos = -1;
            var pageText = textPage.getPageAllText();
            if (!pageText) {
                return false;
            }
            if (!searchContext.isMatchCase) {
                pageText = pageText.toLowerCase();
            }
            var textToFind = searchContext.findWhat;
            textToFind = textToFind.replace(/(^\s*)|(\s*$)/g, ""); //去除左右空格
            if (!searchContext.isMatchCase) {
                textToFind = textToFind.toLowerCase();
            }
            textToFind.replace("  ", " ");
            if (searchContext.isMatchWholeWord) {
                textToFind = ' ' + textToFind + ' ';
                textToFind = ' ' + textToFind + ' ';
            }

            var searchParam = new SearchParams();
            var bFound = _nextIndex(pageText, textToFind, searchContext.searchPos, searchParam);
            if (!bFound) {
                return false;
            }
            var startCharIndex = searchParam.startCharIndex, endCharIndex = searchParam.endCharIndex;
            if (searchContext.isMatchWholeWord) {
                endCharIndex -= 2;
            }
            var objStartIndex = textPage.getObjIndexByCharIndex(startCharIndex);
            var objEndIndex = textPage.getObjIndexByCharIndex(endCharIndex);

            searchContext.resultCharStartPos = startCharIndex;
            searchContext.resultItemStartPos = objStartIndex;
            searchContext.resultItemEndPos = objEndIndex;
            if (objEndIndex === -1 || objStartIndex === -1)
                return false;
            var rectArray = textPage.getPDFRect(objStartIndex, objEndIndex - objStartIndex + 1);
            if (rectArray.length === 0)
                return false;
            searchContext.resultRectArray = rectArray;
            return true;
        }

        /**
         *  在指定的文本里面寻找另一段文本的位置
         * @param pageText 页面文本内容
         * @param textToFind 要搜索的文本
         * @param pos
         * @param {SearchParams} searchParam 搜索上下文
         * @returns {boolean} 搜索成功返回true，否则返回false
         * @private
         */
        function _nextIndex(pageText, textToFind, pos, searchParam) {
            var startPos = searchParam.startCharIndex, endPos = searchParam.endCharIndex;
            var k = pos, j = 0;
            var sLen = pageText.length;
            var tLen = textToFind.length;
            startPos = k;
            while (k < sLen && j < tLen) {
                if (pageText.charAt(k) == textToFind.charAt(j)
                    || ((pageText.charAt(k) == '\r' && k < sLen - 1 && pageText.charAt(k + 1) == '\n') && textToFind.charAt(j) == ' ')
                    || ((pageText.charAt(k) == '\n' && k > 0 && pageText.charAt(k - 1) == '\r') && textToFind.charAt(j) == ' ')
                    || ((j == 0 || j == tLen - 1) && textToFind.charAt(j) == ' ' && !( (pageText.charAt(k) >= 'a' && pageText.charAt(k) <= 'z')
                        || (pageText.charAt(k) >= 'A' && pageText.charAt(k) <= 'Z')) )) {
                    if (j == 0) {
                        startPos = k;
                    }
                    ++k;
                    ++j;
                }
                //If the same, continue backwards
                else if (j != 0 && pageText.charAt(k) == '-') {
                    ++k;
                }
                else if (j != 0 && (pageText.charAt(k) == '\r' && k < sLen - 1 && pageText.charAt(k + 1) == '\n') && !(j - 1 == 0 && textToFind.charAt(j - 1) == ' ')) {
                    ++k;
                }
                else if (j != 0 && (pageText.charAt(k) == '\n' && k > 0 && pageText.charAt(k - 1) == '\r') && !(j - 1 == 0 && textToFind.charAt(j - 1) == ' ')) {
                    ++k;
                }
                else if (pageText.charAt(k) == ' ' && j > 1 && textToFind.charAt(j - 1) == ' ') {
                    ++k;
                }
                else {
                    startPos = startPos + 1;
                    k = startPos;
                    j = 0;
                }
            }
            if (j >= tLen) {
                endPos = k - 1;
            }
            else {
                return false;
            }
            searchParam.startCharIndex = startPos;
            searchParam.endCharIndex = endPos;
            return true;
        }

        /**
         * 获取下一个需要搜索的位置
         * @param txt2Search 当前需要搜索的文本
         * @returns {NextSearchParam | null} 如果是一个新搜索则返回null，否则返回下一个搜索位置
         * @private
         */
        function _getNextSearchIndex(txt2Search) {
            if (_isNewSearch(txt2Search)) {
                return null;
            }
            var pageResult = _pageFindCacheResults[_curSearchedPageIndex];
            if (pageResult.isLastResult(_curSelectedResultIndex)) {
                var nextPage = _curSearchedPageIndex >= _pageFindCacheResults.length - 1 ? 0 : _curSearchedPageIndex + 1;
                var nextCharIndex = 0;
                return new NextSearchParam(nextPage, nextCharIndex);
            }
            else {
                return new NextSearchParam(_curSearchedPageIndex, pageResult.getNextCharIndex(_curSelectedResultIndex));
            }
        }

        /**
         * 获取上一个需要搜索的位置
         * @param txt2Search 当前需要搜索的文本
         * @returns {NextSearchParam | null} 如果是一个新搜索则返回null，否则返回下一个搜索位置
         * @private
         */
        function _getPrevSearchIndex(txt2Search) {
            if (_isNewSearch(txt2Search)) {
                return null;
            }
            var pageResult = _pageFindCacheResults[_curSearchedPageIndex];
            if (pageResult.isFirstResult(_curSelectedResultIndex)) {
                var nextPage = 0;
                if (_curSearchedPageIndex >= 1) {
                    nextPage = _curSearchedPageIndex - 1;
                }
                else {
                    nextPage = _pageFindCacheResults.length - 1;
                }
                return new NextSearchParam(nextPage, -1);
            }
            else {
                return new NextSearchParam(_curSearchedPageIndex, pageResult.getPrevCharIndex(_curSelectedResultIndex));
            }
        }

        /**
         * Search text down
         * @param {String} txt2Search text to search
         */
        this.searchTextDown = function (txt2Search) {
            if(!txt2Search){
                console.warn("Search text cannot be null or empty");
                return false;
            }
            var nextSearchIndex = _getNextSearchIndex(txt2Search);
            var curPageIndex = _readerApp.getMainView().getDocView().getCurPageIndex();
            if (!nextSearchIndex) {
                return _searchText(txt2Search, WebPDF.SearchDirection.Down, curPageIndex, -1);
            }
            else {
                return _searchText(txt2Search, WebPDF.SearchDirection.Down, nextSearchIndex.pageIndex, nextSearchIndex.charIndex);
            }
        };

        /**
         * Search text up
         * @param {String} txt2Search text to search
         */
        this.searchTextUp = function (txt2Search) {
            if(!txt2Search){
                console.warn("Search text cannot be null or empty");
                return false;
            }
            var prevSearchIndex = _getPrevSearchIndex(txt2Search);
            var curPageIndex = _readerApp.getMainView().getDocView().getCurPageIndex();
            if (!prevSearchIndex) {
                curPageIndex = curPageIndex <=0 ? _readerApp.getDocView().getPageCount()-1 : curPageIndex-1;
                return _searchText(txt2Search, WebPDF.SearchDirection.Up, curPageIndex, -1);
            }
            else {
                return _searchText(txt2Search, WebPDF.SearchDirection.Up, prevSearchIndex.pageIndex, prevSearchIndex.charIndex);
            }
        };

        //获取Plugin名称;
        this.getPluginName = function () {
            return WebPDF.FindToolPluginName;
        };
        //插件被注册的时候调用;
        this.onRegister = function () {
        };

        function _bindEvents() {
            $(_readerApp).on(WebPDF.EventList.DOCVIEW_ZOOM_CHANGED, _onDocViewZoom);
        }

        function _onDocViewZoom(data) {
            var pageView = _readerApp.getMainView().getDocView().getPageView(_curSearchedPageIndex);
            if (pageView && _highlightRects) {
                _highLightTextRects(pageView, _highlightRects);
            }
        }

        this.init = function () {
            var mainView = _readerApp.getMainView();
            var docView = mainView.getDocView();
            _searchDivId = docView.getDocViewContainerID() + "_SearchingDiv";  //搜索层的id;
            _searchLoadingTextId = _searchDivId + "_LoadingText";
            var pageCount = docView.getPageCount();
            for (var i = 0; i < pageCount; i++) {
                _pageFindCacheResults[i] = new PageSearchResult();
            }
            var jqMainFrame = $("#" + mainView.getMainFrameID());
           // if (!WebPDF.Environment.mobile) {
                jqMainFrame.append("<div id='" + _searchDivId + "' class='fwr-searching-div' ><div  class='fwr-searching-div-content' /><label class='fxsearching_divcontent' id='" + _searchLoadingTextId + "'>Searching...</label></div>");
           // }
           // else {
            //    jqMainFrame.append("<div id='" + _searchDivId + "' class='fwr-searching-div-wap' ><div  class='fwr-searching-div-content-wap' /><label class='fxsearching_divcontent' style='margin-left: 10px;margin-top: 6px;float: left;' id='" + _searchLoadingTextId + "'>Searching...</label></div>");
            //}
            _changedSearchingDivState(false);
            _bindEvents();
        };

        //模块卸载;
        this.unload = function () {
        };
    };

    exports.createPlugin = function (readerApp) {
        return new WebPDF.FindToolPlugin(readerApp);
    };
});